package org.ala.tiktools.rpc.kcp.protocol.receiver.queue;

import java.util.List;

import org.ala.tiktools.rpc.kcp.protocol.IKcpReceiverQueue;
import org.ala.tiktools.rpc.kcp.protocol.segment.KcpSegment;
import org.ala.tiktools.tools.queue.FixedCircularQueue;
import org.ala.tiktools.tools.queue.IQueueIterator;

import io.netty.buffer.ByteBuf;

/**
 *	循环队列实现
 *
 *	@author ala
 *	@date 2025年4月30日
 */
public class KcpReceiveArrayQueue extends FixedCircularQueue<KcpSegment> implements IKcpReceiverQueue {

	
	/**
	 * 用循环队列记录peekSize
	 */
	
	
	@SuppressWarnings("unchecked")
	public KcpReceiveArrayQueue(int capacity) {
		super(new KcpSegment[capacity]);
		iterator = new KcpReceiveArrayQueueIterator();
	}

	
	/**
     *  rcvQue 中一个完整消息的字节数
     *  <p>	其实可以在add的时候做成O(1)
     *  
     *  @return -1:queue为空 | -2:queue中还么有收到一个完整消息 | >0 一个完整消息的字节数
     */
	@Override
	public int peekSize() {
		if (isEmpty()) { 
			return -1; 
		}
		
		KcpSegment seg = first();
		if (size() < seg.getFrg() + 1) { 
			return -2; 
		}
		
		int len = 0;
		IQueueIterator<KcpSegment> iterator = firstIterator();
		while (iterator.hasNext()) {
			seg = iterator.next();
			len += seg.getData().readableBytes();
			if (seg.getFrg() == 0) { break; }
		}
		return len;
	}

	
	/**
     *  rcvQue -> ByteBuf，直到frg == 0为止
     *  @return  读取的字节数
     */
	@Override
	public int writeToByteBufAndRemove(ByteBuf buf) {
		int len = 0;
		IQueueIterator<KcpSegment> iterator = firstIterator();
		KcpSegment seg = null;
		while (iterator.hasNext()) {
			seg = iterator.removeAndNext();
			len += seg.getData().readableBytes();
			buf.writeBytes(seg.getData());
			
			int frg = seg.getFrg();
			seg.recycle(true);
			if (frg == 0) { break; }
		}
		return len;
	}
	/**
     *  rcvQue[i].data -> bufs[i]，直到frg == 0为止
     *  @return  读取的字节数
     */
	@Override
	public int writeToByteBufsAndRemove(List<ByteBuf> bufs) {
		int len = 0;
		IQueueIterator<KcpSegment> iterator = firstIterator();
		KcpSegment seg = null;
		while (iterator.hasNext()) {
			seg = iterator.removeAndNext();
			len += seg.getData().readableBytes();
			bufs.add(seg.getData());
			
			int frg = seg.getFrg();
			seg.recycle(false);
			if (frg == 0) { break; }
		}
		return len;
	}

	
    /**
     *  将受到的数据按sn号升序放入rcvBuf列表
     *  <p> sn号大概率收到的是排在末尾的
     */
	@Override
	public void parseData(KcpSegment seg) {
		if (isEmpty() || first().getSn() > seg.getSn()) {
			addFirst(seg);
			return;
		}
		
		IQueueIterator<KcpSegment> iterator = lastIterator();
		KcpSegment crt = null;
		while (iterator.hasPrev()) {
			crt = iterator.current();
			//	不处理重复收到的消息
			if (crt.getSn() == seg.getSn()) {
				seg.recycle(true);
				break;
			}
			//	如果crt.sn < seg.sn，则seg插在crt右边
			if (crt.getSn() < seg.getSn()) {
				iterator.insert(seg);
				break;
			}
		}
	}

	@Override
	public boolean isWarningLine(int rcvWnd) {
		return size() >= rcvWnd;
	}


	/**
	 * 	迭代器
	 */
	@SuppressWarnings("rawtypes")
	public class KcpReceiveArrayQueueIterator extends FixedCircularQueue.QueueIterator {

		public boolean insert(KcpSegment e) {
			int p = (posLeft + posOffset) % capacity;
			int r = KcpReceiveArrayQueue.this.insert(p, e);
			if (r <= 0) {return false;}
			//	特殊的，如果执行的是右移，p 和 p+1要换回来
			if (r == 2) { swap(p, (p+1) % capacity); }
			return true;
		}
	}
}
